$Script:thisModuleDirectory = $PSScriptRoot                     # Path \AutoSPUpdater\Modules\AutoSPUpdater\
$Script:modulesDirectory = $PSScriptRoot | Split-Path           # Path \AutoSPUpdater\Modules\
$Script:rootDirectory = $Script:modulesDirectory | Split-Path   # Path \AutoSPUpdater\

$Script:UpdaterModuleDirectory = $PSScriptRoot
$Script:UpdaterModule = $MyInvocation.MyCommand.Definition
$Script:UpdaterLogFilesPath = Join-Path -Path ($Script:rootDirectory | Split-Path) -ChildPath 'LogFiles'    # Path \LogFiles\
$Script:UpdaterUpdatesFilesPath = Join-Path -Path ($Script:rootDirectory | Split-Path) -ChildPath 'Updates'  # Path \Updates\

$paths = @('Functions')
foreach ($path in $paths) {
    "$(Split-Path -Path $MyInvocation.MyCommand.Path)\$path\*.ps1" | Resolve-Path | ForEach-Object {
        if ($_.ProviderPath -notlike '*_*_TEMPLATE*') {
            . $_.ProviderPath 
        }
    }
}

function Write-Log
{
    [CmdletBinding(SupportsShouldProcess=$false)]
    param
    (
        [Parameter(
            Mandatory = $true,
            Position = 0,
            ValueFromPipeline = $true,
            ValueFromPipelineByPropertyName = $true,
            HelpMessage="Objects to log"
        )]
        [Object[]]
        $Object,
        
        [Parameter(
            Mandatory = $false,
            Position = 1,
            ValueFromPipelineByPropertyName = $true,
            HelpMessage = "Objects to log"
        )]
        [Alias("PSPath", "Path")]
        [String]
        $LogFilePath
    )

    process {
        if (!$PSBoundParameters.ContainsKey("LogFilePath")) {
            
            $LogFilesPath  = Get-LogFilesPath
            
            if (Test-InWorkflow) {
                $computerName = Get-Variable "PSComputerName" -ValueOnly -ErrorAction SilentlyContinue
                $computerName = ($computerName -Split '\.')[0]
            } else {
                $computerName = $env:COMPUTERNAME
            }
            
            if ([string]::IsNullOrEmpty($computerName)) {
                $computerName = "THIS_SERVER"
                Write-Error "Cannot determine computer name for use in LogFilePath, using '$computerName' in stead."
            }

            try {
                if (-not (Test-Path -Path $LogFilesPath -PathType Container)) {
                    [Void](New-Item -ItemType Directory -Path $LogFilesPath)
                }
            } catch {
                throw $_
            }

            $LogFilePath = Join-Path -Path $LogFilesPath -ChildPath ("{0}.log" -f $computerName)
        }
        
        foreach ($o in $Object) {
            $logEntry = "[{0}] $o" -f $(Get-Date -Format u)
            Add-Content -LiteralPath $LogFilePath -Value $logEntry -Force
        }
    }
}

function Get-LogLinePrefix
{
    "[{0}]:{1}: " -f $(Get-Date -Format u), $env:COMPUTERNAME
}

[bool]$Global:CustomHostWriteLocalComputerPrefix = $true
function Write-CustomHost
{
    [CmdletBinding(
        SupportsShouldProcess=$false
    )]
    param (
        [Parameter(
            Mandatory = $false,
            ValueFromPipeline = $true,
            ValueFromPipelineByPropertyName = $true,
            HelpMessage = "Objects to display in the console"
        )]
        [Object[]]
        $Object,
        
        [Parameter(
            Mandatory = $false,
            ValueFromPipelineByPropertyName = $true,
            HelpMessage = "Specifies that the content displayed in the console does not end with a newline character."
        )]
        [Switch]$NoNewline,
        
        [Parameter(
            Mandatory = $false,
            ValueFromPipelineByPropertyName = $true,
            HelpMessage = "String to the output between objects displayed on the console."
        )]
        [Object]
        $Separator,

        [Parameter(
            Mandatory = $false,
            ValueFromPipelineByPropertyName = $true,
            HelpMessage = "Specifies the text color. There is no default."
        )]
        [ConsoleColor]
        $ForegroundColor,

        [Parameter(
            Mandatory = $false,
            ValueFromPipelineByPropertyName = $true,
            HelpMessage = "Specifies the background color. There is no default."
        )]
        [ConsoleColor]
        $BackgroundColor,

        [Parameter(
            ValueFromRemainingArguments = $true
        )]
        [String[]]
        $RemainingParams
    )

    begin {
    
        $colorScheme = @{
            "White" = @{
                "ERROR" = @{
                    "ForegroundColor" = "DarkRed"
                    }
                "WHATIF" = @{
                    "ForegroundColor" = "Yellow"
                    }
                "WARNING" = @{
                    "ForegroundColor" = "Black"
                    "BackgroundColor" = "Yellow"
                }
                "NOTE" = @{
                    "ForegroundColor" = "Blue"
                    "BackgroundColor" = "White"
                }
                "SYSTEM" = @{
                }
            }
            
            "DarkMagenta" = @{
                "ERROR" = @{
                    "ForegroundColor" = "DarkRed"
                    }
                "WHATIF" = @{
                    "ForegroundColor" = "Yellow"
                    }
                "WARNING" = @{
                    "ForegroundColor" = "Black"
                    "BackgroundColor" = "Yellow"
                }
                "NOTE" = @{
                    "ForegroundColor" = "Blue"
                    "BackgroundColor" = "White"
                }
                "SYSTEM" = @{
                }
            }
            
            "Black" = @{
                "ERROR" = @{
                    "ForegroundColor" = "Red"
                    }
                "WHATIF" = @{
                    "ForegroundColor" = "Yellow"
                    }
                "WARNING" = @{
                    "ForegroundColor" = "Black"
                    "BackgroundColor" = "Yellow"
                }
                "NOTE" = @{
                    "ForegroundColor" = "Blue"
                    "BackgroundColor" = "White"
                }
                "SYSTEM" = @{
                    "ForgroundColor" = "White"
                }
            }
        }
    }

    process {
    
        $newParams = $PSBoundParameters

        # Let the message dictate colours if BackgroundColor and ForegroundColor are not specified as parameter
        if (($PSBoundParameters["BackgroundColor"] -eq $null) -and ($PSBoundParameters["ForegroundColor"] -eq $null))
        {
            # Change colors depending upon message content
            Switch(@($Object))
            {
                # TODO: ColorScheme toepassen.
                {($_ -like "INFORMATION*") -or ($_ -like "INFORMATIE*") -or ($_ -like "INFO*")} {
                    break;
                }
            
                {($_ -like "ERROR*") -or ($_ -like "FATAL ERROR*") -or ($_ -like "FOUT*") -or ($_ -like "FATALE FOUT*")} {
                    $newParams["ForegroundColor"] = "Red"
                    break;
                }
                
                {($_ -like "What if:*")} {
                    $newParams["ForegroundColor"] = "Yellow"
                    break;
                }
            
                {(($_ -like "WARNING*") -or ($_ -like "WAARSCHUWING*"))} {
                    $newParams["ForegroundColor"] = "Black"
                    $newParams["BackgroundColor"] = "Yellow"
                    break;
                }
            
                {(($_ -like "NOTE*") -or ($_ -like "NOOT*"))} {
                    $newParams["ForegroundColor"] = "Blue"
                    $newParams["BackgroundColor"] = "White"
                    break;
                }

                {(($_ -like "SUCCESS*"))} {
                    $newParams["ForegroundColor"] = "DarkGreen"
                    $newParams["BackgroundColor"] = "White"
                    break;
                }

                {(($_ -like "SYSTEM*"))} {
                    $newParams["ForegroundColor"] = "White"
                    break;
                }
            }
        }
        
        if (Test-InWorkflow) {
            Write-Log $Object

            # Return the object stringified as well.
            # During a workflow, the objects are now shown in the host of the workflow as well
            # Note that these are actually strings being returned and these will only show on display if the calling function is not capturing return values.
            #
            
            #
            # Disabled this for know, otherwise it will mes up the output of our functions, will revise this later when I have more time
            # $Object | foreach { Write-Output "[$($env:COMPUTERNAME)] $_" }
        } elseif (Test-IsRemoted) {
            # Added Write-Host support in remote session: add a prefix [COMPUTERNAME]
            Write-Log $Object
            
            Microsoft.PowerShell.Utility\Write-Host "[$($env:COMPUTERNAME)] " -NoNewLine 
            Microsoft.PowerShell.Utility\Write-Host @newParams
        } else {
        
            # Output object to PowerShells own Write-Host function
            if ($Global:CustomHostWriteLocalComputerPrefix) {
                Microsoft.PowerShell.Utility\Write-Host "[LOCALHOST] " -NoNewLine 
            }
            
            Microsoft.PowerShell.Utility\Write-Host @newParams
        }
    }
}
Set-Alias -Name "Write-Host" -Value "Write-CustomHost" -Scope global